<template>
	<div style="height: 60vh">
		<el-container class="container">
			<el-aside v-show="that.needShow" width="240px" class="select-area" style="overflow: hidden">
				<el-tag class="tag">{{ $t('gong-ju') }}</el-tag>
				<div align="center">
					<div style="padding: 15px 0">
						<el-button size="small" v-for="(tool, index) in that.field.tools" :key="index" :type="that.currentTool.type == tool.type ? 'primary' : 'default'" @click="selectTool(tool.type)">
							{{ tool.name }}
						</el-button>
					</div>
				</div>

				<el-tag class="tag">{{ $t('ji-chu-jie-dian') }}</el-tag>
				<div align="center">
					<el-descriptions :column="setColumn" v-if="that.tag.commonNodeShow">
						<el-descriptions-item v-for="(commonNode, index) in that.field.commonNodes" :key="index">
							<div class="node-item listColor" :type="commonNode.type" belongto="commonNodes">
								<span> {{ commonNode.name }}</span>
							</div>
						</el-descriptions-item>
					</el-descriptions>
				</div>
				<el-tag class="tag">{{ $t('yong-dao-jie-dian') }}</el-tag>
				<div align="center">
					<el-descriptions :column="setColumn" v-if="that.tag.laneNodeShow">
						<el-descriptions-item v-for="(laneNode, index) in that.field.laneNodes" :key="index">
							<div class="node-item listColor" :type="laneNode.type" belongto="laneNodes">
								<span> {{ laneNode.name }}</span>
								<el-icon :type="laneNode.icon" />
							</div>
						</el-descriptions-item>
					</el-descriptions>
				</div>
			</el-aside>
			<el-container>
				<el-header v-show="that.needShow" class="header-option" style="background-color: #fff; padding-right: 10px">
					<el-popconfirm :title="$t('que-ren-yao-zhong-xin-hui-zhi-ma')" @confirm="clear">
						<template #reference>
							<el-button size="small" class="header-option-button"> {{ $t('zhong-hui') }} </el-button>
						</template>
					</el-popconfirm>
					<el-button @click="toggleShowGrid" class="header-option-button" size="small"> {{ $t('yin-cang') }} </el-button>
					<el-button @click="setting" class="header-option-button" size="small">{{ $t('she-zhi') }}</el-button>
					<el-button @click="openTest" class="header-option-button" size="small">JSON</el-button>
				</el-header>
				<el-button-group v-show="!that.needShow">
					<el-button @click="() => selectTool('zoom-in')" size="small" style="margin: 5px">{{ $t('fang-da') }}</el-button>
					<el-button @click="() => selectTool('zoom-out')" size="small" style="margin: 5px">{{ $t('suo-xiao') }}</el-button>
				</el-button-group>
				<!-- 视图标签 -->
				<section style="display: flex; flex: auto">
					<el-main class="flowContent" style="padding: 0">
						<flow-area
							ref="flowArea"
							:browserType="that.browserType"
							:flowData="that.flowData"
							:select="that.currentSelect"
							:selectGroup="that.currentSelectGroup"
							:plumb="that.plumb"
							:currentTool="that.currentTool"
							:activityId="that.activityId"
							@updateSelect="updateSelect"
							@findNodeConfig="findNodeConfig"
							@selectTool="selectTool"
							@getShortcut="getShortcut"
							@saveFlow="saveFlow"
							:thatNeedShow="that.needShow"
						>
						</flow-area>
					</el-main>
				</section>
			</el-container>
			<el-aside width="300px" class="attr-area">
				<flow-attr
					ref="flowAttrForm"
					:plumb="that.plumb"
					:flowData="that.flowData"
					:needShow="that.needShow"
					:select="that.currentSelect"
					:fieldNames="fieldNames"
					@updateFieldNames="updateFieldNames"
					@updateSelect="updateSelect"
					@openUser="openUser()"
					@openRole="openRole()"
				></flow-attr>
			</el-aside>
		</el-container>
		<setting-modal ref="settingModal"></setting-modal>
		<shortcut-modal ref="shortcutModal"></shortcut-modal>
		<test-modal ref="testModal" @loadFlow="loadFlow" @clear123="clear()"></test-modal>
	</div>
</template>

<script setup>
import { reactive, ref, onMounted, nextTick, defineExpose } from 'vue';
import jsplumb from 'jsplumb';
import { tools, commonNodes, laneNodes } from './config/basic-node-config.js';

import { flowConfig } from './config/args-config.js';
import { ZFSN } from './util/ZFSN.js';
import FlowArea from './modules/FlowArea.vue';
import FlowAttr from './modules/FlowAttr.vue';
import SettingModal from './modules/SettingModal.vue';
import ShortcutModal from './modules/ShortcutModal.vue';
import UsingDocModal from './modules/UsingDocModal.vue';
import TestModal from './modules/TestModal.vue';

import useCurrentInstance from '/@/utils/hook/useCurrentInstance';

const { proxy } = useCurrentInstance();
const $t = proxy.$t;
const prop = defineProps({
	fieldNames: {
		type: Boolean,
		default: false,
	},
	needShow: {
		type: Boolean,
		default: false,
	},
	activityId: {
		type: Boolean,
		default: false,
	},
});
const emits = defineEmits(['openRole', 'updateFieldNames', 'openUser']);
let jsPlumb = jsplumb.jsPlumb;
const flowArea = ref();
const testModal = ref();
const shortcutModal = ref();
const settingModal = ref();
const flowAttrForm = ref();
const setColumn = ref(2);

const that = reactive({
	tag: {
		toolShow: true,
		commonNodeShow: true,
		highNodeShow: true,
		laneNodeShow: true,
	},
	browserType: 3,
	plumb: {},
	field: {
		tools: tools,
		commonNodes: commonNodes,
		laneNodes: laneNodes,
	},
	flowData: {
		nodeList: [],
		linkList: [],
		attr: {
			id: '',
		},
		config: {
			showGrid: true,
			showGridText: $t('yin-cang-wang-ge'),
			showGridIcon: 'eye',
		},
		status: flowConfig.flowStatus.CREATE,
		remarks: [],
	},
	currentTool: {
		type: 'drag',
		icon: 'drag',
		name: $t('tuo-zhuai'),
	},
	currentSelect: {},
	currentSelectGroup: [],
	activeShortcut: true,
	linkContextMenuData: flowConfig.contextMenu.link,
	flowPicture: {
		url: '',
		modalVisible: false,
		closable: false,
		maskClosable: false,
	},
	flowLineAdditions: flowConfig.flowLineAdditions,
	fieldNames: prop.fieldNames,
	needShow: prop.needShow,
	activityId: prop.activityId,
});
// 使用时父组件传入的参数
const updateFieldNames = (value) => {
	// console.log(value);
};

const updateSelect = ($event) => {
	that.currentSelect = $event;
};

const openUser = (value) => {
	// $(document).ready("openUser", value);
	emits('openUser', value);
};
//角色选择界面
const openRole = (value) => {
	emits('openRole', value);
};
//角色用户设置必须包含id、name属性的数组
const setFlowAttrForm = (value) => {
	nextTick(() => {
		flowAttrForm.value.setFlowAttrForm(value);
	});
};

const getBrowserType = () => {
	let userAgent = navigator.userAgent;
	let isOpera = userAgent.indexOf($t('opera')) > -1;
	if (isOpera) {
		return 1;
	}
	if (userAgent.indexOf($t('firefox')) > -1) {
		return 2;
	}
	if (userAgent.indexOf($t('chrome')) > -1) {
		return 3;
	}
	if (userAgent.indexOf($t('safari')) > -1) {
		return 4;
	}
	if (userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera) {
		alert($t('ie-liu-lan-qi-zhi-chi-xing-jiao-cha-tui-jian-shi-yong-firefox-huo-chrome'));
		return 5;
	}
	if (userAgent.indexOf($t('trident')) > -1) {
		alert($t('edge-liu-lan-qi-zhi-chi-xing-jiao-cha-tui-jian-shi-yong-firefox-huo-chrome'));
		return 6;
	}
};

const dealCompatibility = () => {
	that.browserType = getBrowserType();
	if (that.browserType == 2) {
		flowConfig.shortcut.scaleContainer = {
			code: 16,
			codeName: $t('shiftchrome-xia-wei-alt'),
			shortcutName: $t('hua-bu-suo-fang'),
		};
	}
};

const initJsPlumb = () => {
	nextTick(() => {
		that.plumb = jsPlumb.getInstance(flowConfig.jsPlumbInsConfig);
		that.plumb.bind('beforeDrop', function (info) {
			let sourceId = info.sourceId;
			let targetId = info.targetId;
			if (sourceId == targetId) return false;
			let filter = that.flowData.linkList.filter((link) => link.sourceId == sourceId && link.targetId == targetId);
			if (filter.length > 0) {
				// that.$message.error("同方向的两节点连线只能有一条！");
				console.log('同方向的两节点连线只能有一条！');
				return false;
			}
			return true;
		});

		that.plumb.bind('connection', function (conn, e) {
			let connObj = conn.connection.canvas;
			let o = {},
				id,
				label;
			if (that.flowData.status == flowConfig.flowStatus.CREATE || that.flowData.status == flowConfig.flowStatus.MODIFY) {
				id = 'link-' + ZFSN.getId();
				label = '';
			} else if (that.flowData.status == flowConfig.flowStatus.LOADING) {
				let l = that.flowData.linkList[that.flowData.linkList.length - 1];
				id = l.id;
				label = l.label;
			}
			connObj.id = id;
			o.type = 'link';
			o.id = id;
			o.sourceId = conn.sourceId;
			o.targetId = conn.targetId;
			o.label = label;
			o.cls = {
				linkType: flowConfig.jsPlumbInsConfig.Connector[0],
				linkColor: flowConfig.jsPlumbInsConfig.PaintStyle.stroke,
				linkThickness: flowConfig.jsPlumbInsConfig.PaintStyle.strokeWidth,
			};
			$('#' + id).bind('contextmenu', function (e) {
				showLinkContextMenu(e);
				that.currentSelect = that.flowData.linkList.filter((l) => l.id == id)[0];
			});
			$('#' + id).bind('click', function (e) {
				let event = window.event || e;
				event.stopPropagation();
				that.currentSelect = that.flowData.linkList.filter((l) => l.id == id)[0];
			});
			if (that.flowData.status != flowConfig.flowStatus.LOADING) that.flowData.linkList.push(o);
		});

		that.plumb.importDefaults({
			ConnectionsDetachable: flowConfig.jsPlumbConfig.conn.isDetachable,
		});
	});
	that.plumb = jsPlumb.getInstance(flowConfig.jsPlumbInsConfig);
	ZFSN.consoleLog([$t('shi-li-hua-jsplumb-cheng-gong')]);
};
const initNodeSelectArea = () => {
	$(document).ready(function () {
		$('.node-item').draggable({
			opacity: flowConfig.defaultStyle.dragOpacity,
			helper: 'clone',
			cursorAt: {
				top: 16,
				left: 60,
			},
			containment: 'window',
			revert: 'invalid',
		});
		ZFSN.consoleLog([$t('chu-shi-hua-jie-dian-xuan-ze-lie-biao-cheng-gong')]);
	});
};

const listenShortcut = () => {
	document.onkeydown = function (e) {
		let event = window.event || e;
		if (!that.activeShortcut) return;
		// let key = event.keyCode;
		nextTick(() => {
			switch (event == $t('enter')) {
				case flowConfig.shortcut.multiple.code:
					flowArea.value._rawValue.that.rectangleMultiple.flag = true;
					break;
				case flowConfig.shortcut.dragContainer.code:
					flowArea.value._rawValue.that.container.dragFlag = true;
					break;
				case flowConfig.shortcut.scaleContainer.code:
					nextTick(() => {
						flowArea.value._rawValue.that.container.scaleFlag = true;
					});
					break;
				case flowConfig.shortcut.dragTool.code:
					selectTool('drag');
					break;
				case flowConfig.shortcut.connTool.code:
					selectTool('connection');
					break;
				case flowConfig.shortcut.zoomInTool.code:
					selectTool('zoom-in');
					break;
				case flowConfig.shortcut.zoomOutTool.code:
					selectTool('zoom-out');
					break;
				case 37:
					moveNode('left');
					break;
				case 38:
					moveNode('up');
					break;
				case 39:
					moveNode('right');
					break;
				case 40:
					moveNode('down');
					break;
			}
		});
	};
	document.onkeyup = function (e) {
		let event = window.event || e;

		let key = event.keyCode;
		if (key == flowConfig.shortcut.dragContainer.code) {
			flowArea.value._rawValue.that.container.dragFlag = false;
		} else if (key == flowConfig.shortcut.scaleContainer.code) {
			event.preventDefault();
			flowArea.value._rawValue.that.container.scaleFlag = false;
		} else if (key == flowConfig.shortcut.multiple.code) {
			flowArea.value._rawValue.that.rectangleMultiple.flag = false;
		}
	};

	ZFSN.consoleLog([$t('chu-shi-hua-kuai-jie-jian-cheng-gong')]);
};
const listenPage = () => {
	window.onbeforeunload = function (e) {
		e = e || window.event;
		if (e) {
			e.returnValue = $t('guan-bi-ti-shi');
		}
		return $t('guan-bi-ti-shi-0');
	};
};
const initFlow = () => {
	if (that.flowData.status == flowConfig.flowStatus.CREATE) {
		that.flowData.attr.id = 'flow-' + ZFSN.getId();
	} else {
		loadFlow();
	}
	ZFSN.consoleLog([$t('chu-shi-hua-liu-cheng-tu-cheng-gong')]);
};

const loadFlow = (json) => {
	// setTimeout(() => {
	// nextTick(() => {
	// 	that.flowLineAdditions.forEach((item) => {
	// 		that.fieldNames.push(item);
	// 	});
	// 	const map = new Map();
	// 	const list = that.fieldNames.filter((key) => !map.has(key.id) && map.set(key.id, 1));
	// 	emits('updateFieldNames', list);
	// });

	// }, 100);
	clear();
	let loadData = JSON.parse(json);
	that.flowData.attr = loadData.attr;
	that.flowData.config = loadData.config;
	that.flowData.status = flowConfig.flowStatus.LOADING;
	that.plumb.batch(function () {
		let nodeList = loadData.nodeList;
		let areaList = loadData.areaList;
		nodeList.forEach(function (node, index) {
			that.flowData.nodeList.push(node);
		});
		if (!!areaList && areaList.length > 0) {
			areaList.forEach(function (node, index) {
				that.flowData.nodeList.push(node);
			});
		}
		let linkList = loadData.linkList;
		nextTick(() => {
			linkList.forEach(function (link, index) {
				that.flowData.linkList.push(link);
				let conn = that.plumb.connect({
					source: link.sourceId,
					target: link.targetId,
					anchor: flowConfig.jsPlumbConfig.anchor.default,
					connector: [
						link.cls.linkType,
						{
							gap: 5,
							cornerRadius: 8,
							alwaysRespectStubs: true,
						},
					],
					paintStyle: {
						stroke: link.cls.linkColor,
						strokeWidth: link.cls.linkThickness,
					},
				});
				if (link.label != '') {
					conn.setLabel({
						label: link.label,
						cssClass: 'linkLabel',
					});
				}
				that.currentSelect = {};
				that.currentSelectGroup = [];
				that.flowData.status = flowConfig.flowStatus.MODIFY;
			});
		});
	}, true);
};
const findNodeConfig = (belongto, type, callback) => {
	let node = null;

	switch (belongto) {
		case 'commonNodes':
			node = commonNodes.filter((n) => n.type == type);
			break;
		case 'laneNodes':
			node = laneNodes.filter((n) => n.type == type);
			break;
	}
	if (node && node.length >= 0) node = node[0];
	callback(node);
};

const selectTool = (type) => {
	let tool = tools.filter((t) => t.type == type);
	if (tool && tool.length >= 0) that.currentTool = tool[0];

	switch (type) {
		case 'drag':
			changeToDrag();
			break;
		case 'connection':
			changeToConnection();
			break;
		case 'zoom-in':
			changeToZoomIn();
			break;
		case 'zoom-out':
			changeToZoomOut();
			break;
	}
};
const changeToDrag = () => {
	that.flowData.nodeList.forEach(function (node, index) {
		let f = that.plumb.toggleDraggable(node.id);
		if (!f) {
			that.plumb.toggleDraggable(node.id);
		}
		if (node.type != 'x-lane' && node.type != 'y-lane') {
			that.plumb.unmakeSource(node.id);
			that.plumb.unmakeTarget(node.id);
		}
	});
};
const changeToConnection = () => {
	that.flowData.nodeList.forEach(function (node, index) {
		let f = that.plumb.toggleDraggable(node.id);
		if (f) {
			that.plumb.toggleDraggable(node.id);
		}
		if (node.type != 'x-lane' && node.type != 'y-lane') {
			that.plumb.makeSource(node.id, flowConfig.jsPlumbConfig.makeSourceConfig);
			that.plumb.makeTarget(node.id, flowConfig.jsPlumbConfig.makeTargetConfig);
		}
	});

	that.currentSelect = {};
	that.currentSelectGroup = [];
};
const changeToZoomIn = () => {
	console.log('切换到放大工具');
};
const changeToZoomOut = () => {
	console.log('切换到缩小工具');
};
const checkFlow = () => {
	let nodeList = that.flowData.nodeList;
	let linkList = that.flowData.linkList;
	let areaList = [];
	for (let index = nodeList.length - 1; index >= 0; index--) {
		const item = nodeList[index];
		if (item.type == 'x-lane' || item.type == 'y-lane') {
			nodeList.splice(index, 1);
			areaList.push(item);
		}
		if (item.setInfo) {
			if ((item.setInfo.nodeDesignate == 'SPECIAL_USER' || item.setInfo.nodeDesignate == 'SPECIAL_ROLE') && item.setInfo.nodeDesignateData.length == 0) {
				// $message.error('节点:' + item.setInfo.nodeName + ',执行权限需要配置！');
				console.log('节点:' + item.setInfo.nodeName + ',执行权限需要配置！');
				return false;
			}
		}
	}
	that.flowData.areaList = areaList;
	linkList.forEach((item) => {
		if (item.compares) {
			for (let index = item.compares.length - 1; index >= 0; index--) {
				const compare = item.compares[index];
				//这些字段没有就去掉条件
				if (!compare.operation || !compare.fieldName || !compare.value) {
					item.compares.splice(index, 1);
				}
			}
		}
	});
	if (nodeList.length <= 0) {
		// $message.error('流程图中无任何节点！');
		console.log('流程图中无任何节点！');
		return false;
	}
	return true;
};
const saveFlow = () => {
	let flowObj = Object.assign({}, that.flowData);
	flowObj.status = flowConfig.flowStatus.SAVE;
	if (!checkFlow()) return;
	let d = JSON.stringify(flowObj);
	console.log(d);
	console.log('保存流程成功！请查看控制台。');
	//$message.success('保存流程成功！请查看控制台。');
	return d;
};
const cancelDownLoadFlowPicture = () => {
	flowPicture.url = '';
	flowPicture.modalVisible = false;
};
const clear = () => {
	that.flowData.nodeList.forEach(function (node, index) {
		that.plumb.remove(node.id);
	});
	that.currentSelect = {};
	that.currentSelectGroup = [];
	that.flowData.nodeList = [];
	that.flowData.linkList = [];
	that.flowData.remarks = [];
};
const toggleShowGrid = () => {
	let flag = that.flowData.config.showGrid;
	if (flag) {
		that.flowData.config.showGrid = false;
		that.flowData.config.showGridText = $t('xian-shi-wang-ge');
		that.flowData.config.showGridIcon = 'eye-invisible';
	} else {
		that.flowData.config.showGrid = true;
		that.flowData.config.showGridText = $t('yin-cang-wang-ge-0');
		that.flowData.config.showGridIcon = 'eye';
	}
};

const setting = () => {
	nextTick(() => {
		settingModal.value._rawValue.open();
	});
};

const shortcutHelper = () => {
	settingModal.value._rawValue.open();
};
const usingDoc = () => {
	window.open('https://gitee.com/yjblogs/VFD?_from=gitee_search');
};
const exit = () => {
	alert($t('tui-chu-liu-cheng-she-ji-qi'));
};
const showLinkContextMenu = (e) => {
	let event = window.event || e;

	event.preventDefault();
	event.stopPropagation();
	$(document).ready()('.vue-contextmenuName-flow-menu').css('display', 'none');
	$(document).ready()('.vue-contextmenuName-node-menu').css('display', 'none');
	let x = event.clientX;
	let y = event.clientY;
	that.linkContextMenuData.axis = { x, y };
};
const deleteLink = () => {
	let sourceId = that.currentSelect.sourceId;
	let targetId = that.currentSelect.targetId;
	that.plumb.deleteConnection(
		that.plumb.getConnections({
			source: sourceId,
			target: targetId,
		})[0]
	);
	let linkList = that.flowData.linkList;
	linkList.splice(
		linkList.findIndex((link) => link.sourceId == sourceId || link.targetId == targetId),
		1
	);
	that.currentSelect = {};
};
const loseShortcut = () => {
	that.activeShortcut = false;
};
const getShortcut = () => {
	that.activeShortcut = true;
};
const openTest = () => {
	nextTick(() => {
		let flowObj = Object.assign({}, that.flowData);
		testModal.value._rawValue.that.flowData = flowObj;
		testModal.value._rawValue.that.testVisible = true;
		// testModal..onClose(flowObj);
	});
};
const moveNode = (type) => {
	let m = flowConfig.defaultStyle.movePx,
		isX = true;
	switch (type) {
		case 'left':
			m = -m;
			break;
		case 'up':
			m = -m;
			isX = false;
			break;
		case 'right':
			break;
		case 'down':
			isX = false;
	}

	if (that.currentSelectGroup.length > 0) {
		that.currentSelectGroup.forEach(function (node, index) {
			if (isX) {
				node.x += m;
			} else {
				node.y += m;
			}
		});
		that.plumb.repaintEverything();
	} else if (that.currentSelect.id) {
		if (isX) {
			that.currentSelect.x += m;
		} else {
			that.currentSelect.y += m;
		}
		that.plumb.repaintEverything();
	}
};

defineExpose({
	updateFieldNames,
	// fieldNames,
	openUser,
	openRole,
	initNodeSelectArea,
	listenShortcut,
	listenPage,
	initFlow,
	loadFlow,
	findNodeConfig,
	selectTool,
	changeToDrag,
	changeToConnection,
	changeToZoomIn,
	changeToZoomOut,
	checkFlow,
	saveFlow,
	cancelDownLoadFlowPicture,
	clear,
	that,
	setFlowAttrForm,
});

// debugger;
onMounted(() => {
	dealCompatibility();
	initNodeSelectArea();
	initJsPlumb();
	listenShortcut();
	initFlow();
	listenPage();
	moveNode();
});
</script>

<style lang="scss" scoped>
@import './style/flow-designer.scss';

// :deep() {

// }
</style>
